package cn.iocoder.yudao.module.member.service.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.*;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.member.controller.admin.profit.vo.ProfitSaveReqVO;
import cn.iocoder.yudao.module.member.controller.admin.siteconfig.vo.SiteConfigurationVo;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserExtendDO;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
import cn.iocoder.yudao.module.member.mq.producer.user.MemberUserProducer;
import cn.iocoder.yudao.module.member.service.device.MemberDeviceRecordService;
import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
import cn.iocoder.yudao.module.member.service.profit.ProfitService;
import cn.iocoder.yudao.module.member.service.siteconfiguration.SiteConfigurationService;
import cn.iocoder.yudao.module.system.api.mail.MailSendApi;
import cn.iocoder.yudao.module.system.api.mail.dto.MailSendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.member.enums.profit.ProfitBizTypeEnum.*;

/**
 * 会员 User Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Valid
@Slf4j
public class MemberUserServiceImpl implements MemberUserService {

    @Resource
    private MemberUserMapper memberUserMapper;
    @Resource
    private MemberUserExtendService memberUserExtendService;

    @Resource
    private SmsCodeApi smsCodeApi;

    @Resource
    private MailSendApi mailSendApi;

    @Resource
    private SocialClientApi socialClientApi;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private SiteConfigurationService siteConfigurationService;

    @Resource
    private MemberPointRecordService pointRecordService;
    @Resource
    private MemberDeviceRecordService memberDeviceService ;
    @Resource
    private MemberUserPriceService memberUserPriceService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private FileApi fileApi;

    /**
     * 注册邮件验证码的缓存
     */
    private static final  String REDIS_KEY_EMAIL = "redis_key_email";

    /**
     * 密码修改
     */
    private static final  String FORGOT_PASSWORD = "forgot_password";
    @Resource
    private ProfitService profitService ;


    /**
     * 默认密码
     */
    private static final  String DEFAULT_PASSWORD = "12345678" ;
    @Override
    public MemberUserDO getUserByMobile(String mobile) {
        return memberUserMapper.selectByMobile(mobile);
    }

    @Override
    public List<MemberUserDO> getUserListByNickname(String nickname) {
        return memberUserMapper.selectListByNicknameLike(nickname);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberUserDO createUserIfAbsent(String mobile, String registerIp, Integer terminal) {
        // 用户已经存在
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user != null) {
            return user;
        }
        // 用户不存在，则进行创建
        return createUser(mobile, null, null, registerIp, terminal);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal) {
        return createUser(null, nickname, avtar, registerIp, terminal);
    }

    private MemberUserDO createUser(String mobile, String nickname, String avtar,
                                    String registerIp, Integer terminal) {
        // 生成密码
        String password = IdUtil.fastSimpleUUID();
        // 插入用户
        MemberUserDO user = new MemberUserDO();
        user.setMobile(mobile);
        user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
        user.setPassword(encodePassword(password)); // 加密密码
        user.setNickname(nickname).setAvatar(avtar); // 基础信息
        if (StrUtil.isEmpty(nickname)) {
            // 昵称为空时，随机一个名字，避免一些依赖 nickname 的逻辑报错，或者有点丑。例如说，短信发送有昵称时~
            user.setNickname("用户" + RandomUtil.randomNumbers(6));
        }
        memberUserMapper.insert(user);
        memberUserExtendService.createMemberUserExtend(user.getId());

        // 发送 MQ 消息：用户创建
//        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
//
//            @Override
//            public void afterCommit() {
//                memberUserProducer.sendUserCreateMessage(user.getId());
//            }
//
//        });
        fileApi.moveFile( CharSequenceUtil.subAfter( avtar, "/get/", false),"icon");
        return user;
    }

    @Override
    public void updateUserLogin(Long id, String loginIp) {
        memberUserMapper.updateById(new MemberUserDO().setId(id)
                .setLoginDate(LocalDateTime.now()));
    }

    @Override
    public MemberUserDO getUser(Long id) {
        MemberUserDO memberUserDO = memberUserMapper.selectById(id);
        MemberUserExtendDO userExtend = memberUserExtendService.getUserExtend(id);
        memberUserDO.setSpendingPower(userExtend.getSpendingPower());
        memberUserDO.setTotalDevice(userExtend.getTotalDevice());
        memberUserDO.setTotalPoint(userExtend.getTotalPoint());
        return memberUserDO;
    }

    @Override
    public List<MemberUserDO> getUserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return memberUserMapper.selectBatchIds(ids);
    }

    @Override
    public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) {
//        MemberUserDO updateObj = BeanUtils.toBean(reqVO, MemberUserDO.class).setId(userId);
        //校验手机是否重复
        validateMobileUnique(userId, reqVO.getMobile());
        MemberUserDO memberUserDO = memberUserMapper.selectById(userId);
        if (ObjectUtil.isEmpty(memberUserDO)){
            throw new RuntimeException("未找到对应的用户信息");
        }
        memberUserDO.setMobile(reqVO.getMobile());
        memberUserDO.setAvatar(reqVO.getAvatar());
        memberUserDO.setEmail(reqVO.getEmail());
        memberUserDO.setPassword( encodePassword(reqVO.getPassword()));
        memberUserDO.setNickname(reqVO.getNickname());
        memberUserMapper.updateById(memberUserDO);
//        memberUserMapper.updateById(updateObj);
//        //修改价格配置
//        if(CollUtil.isNotEmpty(reqVO.getPrices())){
//            memberUserPrices.updateUserPrice(userId, reqVO.getPrices());
//        }
        fileApi.moveFile( CharSequenceUtil.subAfter( reqVO.getAvatar(), "/get/", false),"icon");




    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO) {
        // 1.1 检测用户是否存在
        MemberUserDO user = validateUserExists(userId);
        // 1.2 校验新手机是否已经被绑定
        validateMobileUnique(null, reqVO.getMobile());

        // 2.1 校验旧手机和旧验证码
        // 补充说明：从安全性来说，老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做，所以这里不强制校验
        if (StrUtil.isNotEmpty(reqVO.getOldCode())) {
            smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
                    .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));
        }
        // 2.2 使用新验证码
        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
                .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP()));

        // 3. 更新用户手机
        memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
    }

    @Override
    public void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO) {
        // 1.1 获得对应的手机号信息
        SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo(
                UserTypeEnum.MEMBER.getValue(), reqVO.getCode());
        Assert.notNull(phoneNumberInfo, "获得手机信息失败，结果为空");
        // 1.2 校验新手机是否已经被绑定
        validateMobileUnique(userId, phoneNumberInfo.getPhoneNumber());

        // 2. 更新用户手机
        memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(phoneNumberInfo.getPhoneNumber()).build());
    }

    @Override
    public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) {
        // 检测用户是否存在
        MemberUserDO user = validateUserExists(userId);
        // 校验验证码
        smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode())
                .setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP()));

        // 更新用户密码
        memberUserMapper.updateById(MemberUserDO.builder().id(userId)
                .password(passwordEncoder.encode(reqVO.getPassword())).build());
    }

    @Override
    public void resetUserPassword(AppMemberUserResetPasswordReqVO reqVO) {
        // 检验用户是否存在
        MemberUserDO user = validateUserExists(reqVO.getMobile());

        // 使用验证码
//        smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_RESET_PASSWORD,
//                getClientIP()));
        String code = stringRedisTemplate.opsForValue().get(FORGOT_PASSWORD + reqVO.getEmail()+reqVO.getMobile());
        if (StrUtil.isEmpty(code)){
            throw exception(USER_VERIFICATION_CODE, reqVO.getEmail());
        }
        if (!code.equals(reqVO.getCode())){
            throw exception(USER_VERIFICATION_CODE_ERROR, reqVO.getCode());
        }
        // 更新密码
        memberUserMapper.updateById(MemberUserDO.builder().id(user.getId())
                .password(passwordEncoder.encode(reqVO.getPassword())).build());
    }

    private MemberUserDO validateUserExists(String mobile) {
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user == null) {
            throw exception(USER_MOBILE_NOT_EXISTS);
        }
        return user;
    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    /**
     * 对密码进行加密
     *
     * @param password 密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(MemberUserUpdateReqVO updateReqVO) {
        // 校验存在
        validateUserExists(updateReqVO.getId());
        // 校验手机唯一
        validateMobileUnique(updateReqVO.getId(), updateReqVO.getMobile());

        // 更新
        MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO);
        memberUserMapper.updateById(updateObj);
        fileApi.moveFile( CharSequenceUtil.subAfter( updateReqVO.getAvatar(), "/get/", false),"icon");


    }

    @VisibleForTesting
    MemberUserDO validateUserExists(Long id) {
        if (id == null) {
            return null;
        }
        MemberUserDO user = memberUserMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        return user;
    }

    @VisibleForTesting
    void validateMobileUnique(Long id, String mobile) {
        if (StrUtil.isBlank(mobile)) {
            return;
        }
        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_MOBILE_USED, mobile);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_MOBILE_USED, mobile);
        }
    }

    @Override
    public PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO) {

        PageResult<MemberUserDO> memberUserDOPageResult = memberUserMapper.selectPage(pageReqVO);
        if (ObjectUtil.isEmpty(memberUserDOPageResult)){
            return memberUserDOPageResult;
        }
        List<Long> userIds = memberUserDOPageResult.getList().stream().map(MemberUserDO::getId).collect(Collectors.toList());
        List<MemberUserExtendDO> memberUserExtendDOList=   memberUserExtendService.selectListByIds(userIds);
        Map<Long, MemberUserExtendDO> extendMap = memberUserExtendDOList.stream().collect(Collectors.toMap(MemberUserExtendDO::getUserId, Function.identity()));
        memberUserDOPageResult.getList().stream().forEach(t->{
            if (extendMap.containsKey(t.getId())){
                MemberUserExtendDO memberUserExtendDO = extendMap.get(t.getId());
                t.setSpendingPower(memberUserExtendDO.getSpendingPower());
                t.setTotalPoint(memberUserExtendDO.getTotalPoint());
                t.setTotalDevice(memberUserExtendDO.getTotalDevice());
            }
        });
        return memberUserDOPageResult;
    }

//    @Override
//    public void updateUserLevel(Long id, Long levelId, Integer experience) {
//        // 0 代表无等级：防止UpdateById时，会被过滤掉的问题
//        levelId = ObjectUtil.defaultIfNull(levelId, 0L);
//        memberUserMapper.updateById(new MemberUserDO()
//                .setId(id)
//                .setLevelId(levelId).setExperience(experience)
//        );
//    }

//    @Override
//    public Long getUserCountByGroupId(Long groupId) {
//        return memberUserMapper.selectCountByGroupId(groupId);
//    }
//
//    @Override
//    public Long getUserCountByLevelId(Long levelId) {
//        return memberUserMapper.selectCountByLevelId(levelId);
//    }

    @Override
    public Long getUserCountByTagId(Long tagId) {
        return memberUserMapper.selectCountByTagId(tagId);
    }

//    @Override
//    public void updateUserPoint(Long id, BigDecimal point) {
//            memberUserMapper.updatePointIncr(id, point);
//
//    }

    /**
     * 更新用户的设备
     *
     * @param userId  用户编号
     * @param device  积分数量
     * @param addFlag
     * @return 更新结果
     */
    @Override
    public void updateUserDevice(Long userId, Integer device,  Boolean addFlag) {
//        MemberUserDO memberUserDO = memberUserMapper.selectById(userId);
        MemberUserExtendDO userExtend = memberUserExtendService.getUserExtend(userId);
        //
        Integer totalDevice = userExtend.getTotalDevice();
        if (addFlag){
            totalDevice = totalDevice+device;
            memberDeviceService.createDeviceRecord(userId, device, MemberPointBizTypeEnum.ADMIN_ADD_DEVICE, null,totalDevice,userExtend.getTotalDevice(),null,null,null);
        }else {
            totalDevice = totalDevice-device;
            if (totalDevice<0){
                throw exception(USER_DEVICE_NOT_ZERO);
            }
            memberDeviceService.createDeviceRecord(userId, device, MemberPointBizTypeEnum.ADMIN_REDUCE_DEVICE, null,totalDevice,userExtend.getTotalDevice(),null,null,null);
        }
        userExtend.setTotalDevice(totalDevice);
        log.info("后台更新设备数量userId={}",userExtend.getUserId());
        memberUserExtendService.updateById(userExtend);

    }

    /**
     * 前端用户注册
     *
     * @param appMemberUserVo
     */
    @Override
    @Transactional
    public void createUserFront(AppMemberUserVo appMemberUserVo) {
        //校验验证码
        String code = stringRedisTemplate.opsForValue().get(REDIS_KEY_EMAIL + appMemberUserVo.getEmail());
        if (StrUtil.isEmpty(code)){
            throw exception(USER_VERIFICATION_CODE, appMemberUserVo.getEmail());
        }
        if (!code.equals(appMemberUserVo.getVerificationCode())){
            throw exception(USER_VERIFICATION_CODE_ERROR, appMemberUserVo.getVerificationCode());
        }
        //手机号唯一验证
        MemberUserDO memberUserDO = memberUserMapper.selectByMobile(appMemberUserVo.getMobile());
        if (ObjectUtil.isNotEmpty(memberUserDO)){
            throw exception(AUTH_MOBILE_USED, appMemberUserVo.getMobile());
        }
        try {
            // 插入用户
            MemberUserDO user = new MemberUserDO();
            user.setMobile(appMemberUserVo.getMobile());
            user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
            user.setPassword(encodePassword(appMemberUserVo.getPassword())); // 加密密码
            user.setNickname(appMemberUserVo.getUsername()); // 基础信息

            user.setMacFlag(CommonStatusEnum.DISABLE.getStatus());
            user.setUpFlag(CommonStatusEnum.DISABLE.getStatus());
            String cardKey = UUID.randomUUID().toString().replace("-","").substring(0,32);
            user.setUserToken(cardKey);
            user.setEmail(appMemberUserVo.getEmail());
            if (StrUtil.isEmpty(user.getNickname())) {
                // 昵称为空时，随机一个名字，避免一些依赖 nickname 的逻辑报错，或者有点丑。例如说，短信发送有昵称时~
                user.setNickname("用户" + RandomUtil.randomNumbers(6));
            }
            memberUserMapper.insert(user);
            memberUserExtendService.createMemberUserExtend(user.getId());
        } catch (Exception e) {
           log.info("用户注册失败",e);
        }

    }

    /**
     * 后台手动更新用户信息
     *
     * @param updateReqVO
     */
    @Override
    @Transactional
    public void updateByBackend(MemberUserUpdateVo updateReqVO) {
        //todo xiawei  手动更新会员信息

        //设备数与余额是否修改
        MemberUserDO userByDb = getUser(updateReqVO.getId());
        userByDb.setStatus(Integer.valueOf(updateReqVO.getStatus()));
        MemberUserExtendDO userExtend = memberUserExtendService.getUserExtend(updateReqVO.getId());
        if (ObjectUtil.isNull(userExtend)){
            throw exception(USER_NOT_EXISTS);
        }
        //变动前积分
        BigDecimal totalPointFront = userExtend.getTotalPoint();
        //变动前设备
        Integer totalDeviceFront = userExtend.getTotalDevice();
        //积分变动记录
        if (userExtend.getTotalPoint().compareTo(updateReqVO.getTotalPoint()) < 0){
            pointRecordService.createPointRecord(updateReqVO.getId(), updateReqVO.getTotalPoint().subtract(userExtend.getTotalPoint()), MemberPointBizTypeEnum.ADMIN_ADD_POINT, null,updateReqVO.getTotalPoint(),totalPointFront,null,null,null);
        }else if (userExtend.getTotalPoint().compareTo(updateReqVO.getTotalPoint()) > 0){
            pointRecordService.createPointRecord(updateReqVO.getId(), userExtend.getTotalPoint().subtract(updateReqVO.getTotalPoint()), MemberPointBizTypeEnum.ADMIN_REDUCE_POINT, null,updateReqVO.getTotalPoint(),totalPointFront,null,null,null);
        }
        //设备数变动记录
        if (userExtend.getTotalDevice() -(updateReqVO.getTotalDevice()) <0){
            memberDeviceService.createDeviceRecord(updateReqVO.getId(), updateReqVO.getTotalDevice()-userExtend.getTotalDevice(), MemberPointBizTypeEnum.ADMIN_ADD_DEVICE, null,updateReqVO.getTotalDevice(),totalDeviceFront,null,null,null);
        }else if (userExtend.getTotalDevice() -(updateReqVO.getTotalDevice())>0){
            memberDeviceService.createDeviceRecord(updateReqVO.getId(), userExtend.getTotalDevice()-updateReqVO.getTotalDevice(), MemberPointBizTypeEnum.ADMIN_REDUCE_DEVICE, null,updateReqVO.getTotalDevice(),totalDeviceFront,null,null,null);
        }
        userExtend.setTotalPoint(updateReqVO.getTotalPoint());
        userExtend.setTotalDevice(updateReqVO.getTotalDevice());
        memberUserMapper.updateById(userByDb);
        memberUserExtendService.updateMemberUserExtend(updateReqVO);
        if(CollUtil.isNotEmpty(updateReqVO.getVoList())){
            //更新用户私有价格池
            memberUserPriceService.updateUserPrice(updateReqVO.getId(),updateReqVO.getVoList());
        }
    }

    /**
     * 更新用户关联密钥
     *
     * @param loginUserId
     * @return
     */
    @Override
    @Transactional
    public String tokenUpdate(Long loginUserId) {
        MemberUserDO userByDb = getUser(loginUserId);
        if (ObjectUtil.isNull(userByDb)){
            throw exception(USER_NOT_EXISTS);
        }

        String cardKey = UUID.randomUUID().toString().replace("-","").substring(0,32);
        userByDb.setUserToken(cardKey);
        memberUserMapper.updateById(userByDb);
        return cardKey;
    }

    @Override
    public Long count() {
        return memberUserMapper.selectCountByStatus();
    }

    /**
     * 启用用户
     *
     * @param ids
     */
    @Override
    @Transactional
    public void enable(List<Long> ids,String type) {

        if (Objects.equals(type, "1")){
            memberUserMapper.updateStatusByIds(ids,CommonStatusEnum.ENABLE.getStatus());
        }
        if (Objects.equals(type, "2")){
            memberUserMapper.updateMacStatusByIds(ids,CommonStatusEnum.ENABLE.getStatus());
        }
        if (Objects.equals(type, "3")){
            memberUserMapper.updateUpStatusByIds(ids,CommonStatusEnum.ENABLE.getStatus());
        }

    }

    /**
     * 发送邮件
     *
     * @param memBerSendEmail
     */
    @Override
    public void sendEmail(MemBerSendEmail memBerSendEmail) {
        Long count = count();
        MemberUserPageReqVO memberUserPageReqVO = new MemberUserPageReqVO();
        memberUserPageReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
        if(count<200){
            memberUserPageReqVO.setPageNo(1);
            memberUserPageReqVO.setPageSize(Math.toIntExact(count));
            PageResult<MemberUserDO> memberUserDOPageResult = memberUserMapper.selectPage(memberUserPageReqVO);
            List<String> emails = memberUserDOPageResult.getList().stream().map(MemberUserDO::getEmail).collect(Collectors.toList());
            //发送短信
            emails.forEach(t->{
                MailSendSingleToUserReqDTO dTO = new MailSendSingleToUserReqDTO();
                dTO.setMail(t);
                dTO.setTemplateCode(memBerSendEmail.getTemplateCode());
                dTO.setTemplateParams(memBerSendEmail.getTemplateParams());
                mailSendApi.sendSingleMailToMember(dTO);
            });
        }else {
            long l = count / 200;
            long l1 = count % 200;
            if (l1!=0){
                l = l+1;
            }
            for (int i = 0; i < l; i++) {
                memberUserPageReqVO.setPageNo(i);
                memberUserPageReqVO.setPageSize(i*200);
                PageResult<MemberUserDO> memberUserDOPageResult = memberUserMapper.selectPage(memberUserPageReqVO);
                List<String> emails = memberUserDOPageResult.getList().stream().map(MemberUserDO::getEmail).collect(Collectors.toList());
                //发送短信
                emails.forEach(t->{
                    MailSendSingleToUserReqDTO dTO = new MailSendSingleToUserReqDTO();
                    dTO.setMail(t);
                    dTO.setTemplateCode(memBerSendEmail.getTemplateCode());
                    dTO.setTemplateParams(memBerSendEmail.getTemplateParams());
                    mailSendApi.sendSingleMailToMember(dTO);
                });
            }
        }
    }

    /**
     * 禁用
     *type 1：禁用 2：mac 3 上传
     *
     * @param ids
     */
    @Override
    public void disable(List<Long> ids ,String type) {
        if (Objects.equals(type, "1")){
            memberUserMapper.updateStatusByIds(ids,CommonStatusEnum.DISABLE.getStatus());
        }
        if (Objects.equals(type, "2")){
            memberUserMapper.updateMacStatusByIds(ids,CommonStatusEnum.DISABLE.getStatus());
        }
        if (Objects.equals(type, "3")){
            memberUserMapper.updateUpStatusByIds(ids,CommonStatusEnum.DISABLE.getStatus());
        }
    }

    @Override
    public void delete(String id) {
        memberUserMapper.deleteById(id);
    }

    /**
     * 修改用户积分
     *
     * @param id
     * @param point
     * @param valueOf
     */
    @Override
    @Transactional
    public void updateRecord(Long id, BigDecimal point, String valueOf,boolean addFlag) {
//        MemberUserDO memberUserDO = memberUserMapper.selectById(id);
        MemberUserExtendDO userExtend = memberUserExtendService.getUserExtend(id);
        //变动前的积分
        BigDecimal totalPointFront = userExtend.getTotalPoint();
         BigDecimal totalPoint = userExtend.getTotalPoint();
        if (addFlag){
            //增加
            totalPoint = totalPoint.add(point);
            pointRecordService.createPointRecord(id, point, MemberPointBizTypeEnum.ADMIN_ADD_POINT, null,totalPoint,totalPointFront,null,null,null);

        }else {
            totalPoint = totalPoint.subtract(point);
            if (totalPoint.compareTo(BigDecimal.ZERO)<0){
                throw exception(USER_POINT_NOT_ZERO);
            }
            pointRecordService.createPointRecord(id, point, MemberPointBizTypeEnum.ADMIN_REDUCE_POINT, null,totalPoint,totalPointFront,null,null,null);
        }

        userExtend.setTotalPoint(totalPoint);
        log.info("后台更新积分数量userId={}",userExtend.getUserId());
        memberUserExtendService.updateById(userExtend);
    }

    @Override
    public String updateUserAvatar(Long loginUserId, InputStream inputStream) {
        validateUserExists(loginUserId);
        // 存储文件
        String avatar = fileApi.createFile(IoUtil.readBytes(inputStream));
        // 更新路径
        MemberUserDO memberUserDO  = memberUserMapper.selectById(loginUserId);
        memberUserDO.setAvatar(avatar);
        memberUserMapper.updateById(memberUserDO);
        fileApi.moveFile( CharSequenceUtil.subAfter( avatar, "/get/", false),"icon");

        return avatar;
    }

    /**
     * 用户积分操作
     *
     * @param id 用户id
     * @param point  变动积分
     * @param type    MemberPointBizTypeEnum   现在默认P8 p12 上传在这里询价
     */
    @Override
    @Transactional
    public void updateRecordByType(Long id, BigDecimal point, Integer type) {
        MemberPointBizTypeEnum memberPointBizTypeEnum = MemberPointBizTypeEnum.getByType(type);
        if (memberPointBizTypeEnum == null){
            throw exception(POINT_ENUM_EXISTS);
        }
        Date date = new Date();
        BigDecimal costPrice = BigDecimal.ZERO;
        if(ObjectUtil.isNull(point)){
            SiteConfigurationVo config = siteConfigurationService.getConfig();
            ProfitSaveReqVO profitSaveReqVO = new ProfitSaveReqVO();
            if (memberPointBizTypeEnum.equals(MemberPointBizTypeEnum.REDUCE_UP_P8_SPENDING_POWER)){
                //P8
                point = config.getPrivatePoolPrice();
                costPrice = config.getPrivatePoolCost();
                profitSaveReqVO.setType(ADD_UP_LOAD_PRIVATE.getType());
            }
            if (memberPointBizTypeEnum.equals(MemberPointBizTypeEnum.REDUCE_UP_P12_SPENDING_POWER)){
                //P8
                point = config.getUpPrice();
                costPrice = config.getUpCost();
                profitSaveReqVO.setType(ADD_UP_LOAD.getType());
            }
            if(profitSaveReqVO.getType().equals(ADD_UP_LOAD.getType()) || ADD_UP_LOAD_PRIVATE.getType().equals(profitSaveReqVO.getType())){
                profitSaveReqVO.setPrice(point);
                profitSaveReqVO.setCostPrice(costPrice);
                profitSaveReqVO.setProfit(point.subtract(costPrice));
                profitSaveReqVO.setYear(DateUtil.year(date));
                profitSaveReqVO.setMonth(DateUtil.month(date));
                profitService.createProfit(profitSaveReqVO);
            }
        }
        MemberUserExtendDO memberUserExtendDO = memberUserExtendService.getUserExtend(id);
        if (ObjectUtil.isNull(memberUserExtendDO)){
            throw exception(USER_NOT_EXISTS);
        }
        //变动前的积分
        BigDecimal totalPointFront = memberUserExtendDO.getTotalPoint();
        BigDecimal totalPoint = memberUserExtendDO.getTotalPoint();
        boolean add = memberPointBizTypeEnum.isAdd();
        if (add){
            //增加
            totalPoint =   totalPoint.add(point);
        }else {
            //减少
           totalPoint =   totalPoint.subtract(point);
        }
        memberUserExtendDO.setTotalPoint(totalPoint);
        pointRecordService.createPointRecord(id, point, memberPointBizTypeEnum, null,totalPoint,totalPointFront,null,null,null);
        //根据操作类型判断是否增加消费力
        boolean spendingPowerFlag = memberPointBizTypeEnum.isSpendingPowerFlag();
        if (spendingPowerFlag){
            memberUserExtendDO.setSpendingPower(memberUserExtendDO.getSpendingPower().add(point));
        }
        log.info("P8上传扣减积分userId={}",memberUserExtendDO.getUserId());
        memberUserExtendService.updateById(memberUserExtendDO);

    }


    /**
     * 后台用户重置密码
     * @param id
     */
    @Override
    @Transactional
    public void resetPasswordByAdmin(Long id) {
        MemberUserDO memberUserDO = memberUserMapper.selectById(id);
        if (ObjectUtil.isNull(memberUserDO)){
            throw exception(USER_NOT_EXISTS);
        }
        String password = passwordEncoder.encode(DEFAULT_PASSWORD);
        memberUserDO.setPassword(password);
        memberUserMapper.updateById(memberUserDO);
    }

    /**
     * 未登录时发送邮件信息
     *
     * @param mobile
     */
    @Override
    public void sendPasswordMail(String mobile) {
        MemberUserDO userByMobile = this.getUserByMobile(mobile);
        if (ObjectUtil.isNull(userByMobile)){
            throw exception(USER_NOT_EXISTS);
        }
        mailSendApi.sendSingleMailToMemberByMobile(userByMobile.getEmail(),mobile);
    }

    /**
     * 通过Token查询用户
     *
     * @param token 手机
     * @return 用户对象
     */
    @Override
    public MemberUserDO getUserByUserToken(String token) {
        return memberUserMapper.getUserByUserToken(token);
    }

    @Override
    public void updateBatchInfo(MemberUserUpdateBatchReqVO updateReqVO) {

        MemberUserDO user = this.getUser(Long.parseLong(updateReqVO.getId()));
        if(user != null){
            user.setBatchFlag(updateReqVO.getBatchFlag());
            user.setBatchNum(updateReqVO.getBatchNum());
            memberUserMapper.updateById(user);
        }
    }


}
